
module DistributedWorker
  
  # == Overview
  # Application logic for a client instance.
  module Client
    
    # == Overview
    # Receive UDP dataset packets from a server
    module DataListener
      
      # Receive, parse and store a dataset from a server
      def receive_data(data)
        
        # parse application id from packet
        # find or create data row by datarow id
        # for each column in datarow
        # => get value for column name in data packet
        # end
        # datarow.save
        
      end
      
    end
    
    # == Overview
    # Report results back to a server
    class DataReporter
      
      # Query computed results and transmit back to server for marshaling.
      def return_results()
        
        # for each application
        # => for each datarow in application.datarows where result != null
        # => => send data packet with application id & result to server
        # => end
        # end
        
      end
      
    end
    
    # == Overview
    # Protected sandbox object to mixin controller from the server/application.
    class Task
      @@processes = Array.new
      
      def Task.processes
        @@processes ||= Array.new
      end
      
      # Initialize a new process controller in its own process and let it run.
      def Task.create(mixin)
        @@processes << Process.fork {
          task = Task.new(mixin)
          loop do
            begin
              process.run()
            rescue StandardError => e
              puts "Error running task\n#{e}"
            end
            sleep(100)
          end
        }
      end
      
      # Shutdown all running tasks
      def Task.teardown()
        for process in @@processes
          Process.kill('KILL', process) 
        end
      end
      
      # Create a sandbox for the process controller to protect the application.
      # TODO: build object in sandbox
      # TODO: set security level of sandbox object
      def initialize(mixin, sandbox = true, nice = true)
        unless mixin.class == Module
          raise ArgumentError('mixin must be a Module')
        end
        if sandbox
          # TODO: setup sandbox
        end
        Process.setpriority(Process::PRIO_PROCESS, 0, 0) if nice
        self.extend(mixin)
      end
      
      # Query available DataSets for this task that need to be computed.
      # TODO: add application param for query
      def run()
        #sets = Dataset.find(:all, :conditions => ['result IS NULL'], :limit => @max)
        #for dataset in sets
        #  process(dataset)
        #  dataset.save
        #end
      end
      
      # Process a dataset (extended by controller module).
      def process(dataset)
      end
      
      module Test
        def process(dataset)
          puts "test module process"
        end
      end
      
    end
    
  end
  
end